﻿--[[
    Ресурс сохраняет все глобальные переменные, включая МТА функции, в
    файл `mtasaGlobals_TIME.txt` в папке этого же ресурса. Юзайте
    команду /saveGlobals в чате или saveGlobals в консоли.

    Этот инструмент удобен для составления списков всех МТА функций
    для последующего их добавления в подсветку синтаксиса вашего
    редактора скриптов. Кроме этих функций в экспорт включены другие
    глобальные переменные. Например, такие как глобальные предопределенные
    МТА переменные.

    Ресурс разбивает все МТА функции на три категории:
      - только серверные
      - только клиентские
      - общие для сервера и клиента

    MX_Master, 18.05.2011 23:54:49, протестировано в MTA:SA 1.1
]]

-- простой поиск по таблице
local function fFindInTable ( t, value )
    if type(t) ~= 'table' or value == nil then
        return nil
    end

    local k = next(t)
    while k do
        if t[k] == value then
            return k
        end

        k = next(t,k)
    end

    return nil
end





-- таблицы для списков всех глобальных переменных
local tServerFuncList = {}
local tServerVarsList = {}
local tGeneralFuncList = {}
local tGeneralVarsList = {}

-- заполняем серверные списки
for i,v in pairs(_G) do
    if type(v) == 'function' then
        table.insert( tServerFuncList, tostring(i) )
--[[
    -- раскоментируйте, если нужно содержимое глобальных таблиц
    elseif type(v) == 'table' and v ~= _G then
        for subI,subV in pairs(v) do
            if type(subV) == 'function' then
                table.insert( tServerFuncList, tostring(i)..'.'..tostring(subI) )
            end
        end
]]
    else
        table.insert( tServerVarsList, tostring(i) )
    end
end





-- обработка ответа со списками клиентских глобальных переенных
function fOnClientGlobalsList ( tClientVer, tClientFuncList, tClientVarsList )
    outputChatBox( 'Получены списки клиентских глобальных переменных', source, 0,0,255 )

    if  type(tClientFuncList) ~= 'table' or
        type(tClientVarsList) ~= 'table'
    then
        outputChatBox( 'Список глобальных переменных клиента имеет неверный формат', source, 0,0,255 )
        return
    end

    if type(tClientVer) ~= 'table' then tClientVer = {} end



    -- узнаем текущее время сервера
    local tTime = getRealTime()
    local sTime
    if tTime.timestamp then
        sTime = tTime.timestamp
    else
        sTime = tTime.hour..tTime.minute..tTime.second..tTime.monthday..tTime.month..(tTime.year + 1900)
    end

    -- версии сервера/клиента как строки
    local sServerVer = getVersion().sortable or getVersion().tag or getVersion().mta
    local sClientVer = tClientVer.sortable or tClientVer.tag or tClientVer.mta or 'unknown'

    -- зададим имя экспорт файла
    local sFileName = 'mtasaGlobals_'..sTime..'.txt'




    -- создаем файл
    local uFile = fileCreate(sFileName)
    if not uFile then
        outputChatBox( 'Не удалось создать экспорт файл', source, 0,0,255 )
        return
    end



    -- сортируем МТА функции на три категории
    local nFoundPos
    local n = 1

    while tServerFuncList[n] do
        nFoundPos = fFindInTable( tClientFuncList, tServerFuncList[n] )

        if nFoundPos then
            table.insert( tGeneralFuncList, tServerFuncList[n] )
            table.remove( tServerFuncList, n )
            table.remove( tClientFuncList, nFoundPos )
        else
            n = n + 1
        end
    end

    while tClientFuncList[n] do
        nFoundPos = fFindInTable( tServerFuncList, tClientFuncList[n] )

        if nFoundPos then
            table.insert( tGeneralFuncList, tClientFuncList[n] )
            table.remove( tClientFuncList, n )
            table.remove( tServerFuncList, nFoundPos )
        else
            n = n + 1
        end
    end



    -- сортируем все списки по алфавиту
    table.sort(tServerFuncList)
    table.sort(tClientFuncList)
    table.sort(tGeneralFuncList)

    table.sort(tServerVarsList)
    table.sort(tClientVarsList)



    -- пишем в файл версии сервера/клиента
    fileWrite( uFile, "Server version: "..sServerVer.."\r\nClient version: "..sClientVer.."\r\n\r\n" )

    -- пишем в файл все списки
    fileWrite( uFile, "Server only functions ("..#tServerFuncList.."):\r\n-------------------------------------------------------------------------------------\r\n" )
    for n,_ in ipairs(tServerFuncList) do
        fileWrite( uFile, tServerFuncList[n].."\r\n" )
    end

    fileWrite( uFile, "\r\nClient only functions ("..#tClientFuncList.."):\r\n-------------------------------------------------------------------------------------\r\n" )
    for n,_ in ipairs(tClientFuncList) do
        fileWrite( uFile, tClientFuncList[n].."\r\n" )
    end

    fileWrite( uFile, "\r\nGeneral for server and client functions ("..#tGeneralFuncList.."):\r\n-------------------------------------------------------------------------------------\r\n" )
    for n,_ in ipairs(tGeneralFuncList) do
        fileWrite( uFile, tGeneralFuncList[n].."\r\n" )
    end

    -- пишем списки предопределенных МТА переменных
    fileWrite( uFile, "\r\nServer vars ("..#tServerVarsList.."):\r\n-------------------------------------------------------------------------------------\r\n" )
    for n,_ in ipairs(tServerVarsList) do
        fileWrite( uFile, tServerVarsList[n].."\r\n" )
    end

    fileWrite( uFile, "\r\nClient vars ("..#tClientVarsList.."):\r\n-------------------------------------------------------------------------------------\r\n" )
    for n,_ in ipairs(tClientVarsList) do
        fileWrite( uFile, tClientVarsList[n].."\r\n" )
    end



    -- закрываем файл
    fileClose(uFile)
    outputChatBox( 'Создан экспорт файл `'..sFileName..'` в папке ресурса', source, 0,0,255 )
end

-- серверное событие для приемки ответов от клиентов
addEvent( 'onGlobalsList', true )
addEventHandler( 'onGlobalsList', root, fOnClientGlobalsList )





-- серверная команда для экспорта
addCommandHandler( 'saveGlobals',
    function ( uPlayer )
        if not uPlayer or getElementType(uPlayer) ~= 'player' then return end

        outputChatBox( 'Отправляется запрос от сервера в клиент..', uPlayer, 0,0,255 )
        triggerClientEvent( uPlayer, 'getClientGlobals', root )
    end,

    false,
    false
)
